<template>
    <div class="boxs">
        <el-card>
            <el-form :model="queryParams" ref="queryForm" :inline="true">
                <el-form-item :label="$t('upload.updateTime')">
                    <el-date-picker v-model="value1" value-format="yyyy-MM-dd" type="daterange" range-separator="-"
                        :start-placeholder="$t('table.start')" :end-placeholder="$t('table.end')" @change="timeChange">
                    </el-date-picker>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" icon="el-icon-search" size="small"
                        @click="handleQuery">{{ $t('table.search') }}</el-button>
                    <el-button icon="el-icon-refresh" size="small" @click="resetQuery">{{ $t('table.reset') }}</el-button>
                </el-form-item>
            </el-form>
            <div class="flex_between">
                <div></div>
                <el-button type="primary" icon="el-icon-upload" size="small"
                    @click="handleEdit">{{ $t('upload.upload') }}</el-button>
            </div>
            <el-table border :data="moreArr" style="margin-top: 15px" v-loading="loading">
                <el-table-column label="index" align="center" width="60" type="index" />
                <el-table-column :label="$t('upload.ProjectName')" align="center" prop="type" />
                <el-table-column :label="$t('upload.title')" align="center" prop="title" />
                <el-table-column :label="$t('upload.content')" align="center" prop="content" />

                <el-table-column :label="$t('upload.versionName')" align="center" width="180" prop="version" />

                <el-table-column :label="$t('upload.versionCode')" align="center" width="120" prop="version_code">
                </el-table-column>
                <el-table-column :label="$t('upload.updateTime')" align="center" width="180" prop="update_date" />
            </el-table>
            <pagination v-show="total > 0" :total="total" :page.sync="queryParams.page" :limit.sync="queryParams.size"
                @pagination="getMore" />
        </el-card>

        <el-dialog :title="$t('upload.upload')" :visible.sync="dialogVisible" width="800px">
            <el-form class="demo-form-inline" label-width="80px" :model="form" :rules="rules" ref="ruleForm">
                <el-row>
                    <el-col :span="24">
                        <el-form-item :label="$t('upload.content')" prop="description">
                            <el-input :autosize="{ minRows: 4 }" type="textarea" v-model="form.description"
                                placeholder="" resize="none" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="24">
                        <el-form-item :label="$t('upload.file')" prop="file">
                            <el-upload class="upload-demo" drag limit="1"
                                action="https://jsonplaceholder.typicode.com/posts/" multiple
                                :http-request="uploadHandel" :on-remove="remeveFile" ref="upload">
                                <i class="el-icon-upload"></i>
                                <div class="el-upload__text">
                                    {{ $t('upload.uploadText') }}<em> {{ $t('upload.uploadText1') }}</em>
                                </div>
                            </el-upload>
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>

            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">{{ $t('tagsView.close') }}</el-button>
                <el-button type="warning" :loading="addLoading" @click="affirm">{{ $t('table.confirm') }}</el-button>
            </div>
        </el-dialog>
    </div>
</template>
<script>
import { findUploadPckageList, upload, proxyUpload, uploadChunkHandel, mergeChunksHandel } from "@/api/uploadPackage";

import pk from "@/utils/pk";
export default {
    name: "uploadPackage",
    data() {
        return {
            queryParams: {
                page: 1,
                size: 10,
                dateRange: {
                    start: "",
                    end: "",
                },
                type: "",
            },
            total: 0,
            loading: false,
            addLoading: false,
            moreArr: [],
            dialogVisible: false,
            form: {
                description: "",
                file: "",
            },
            search: "",
            rules: {
                description: [
                    { required: true, message: "请输入描述", trigger: "blur" },
                ],
                file: [{ required: true, message: "请上传文件", trigger: "blur" }],
            },
            value1: "",
            isUploading: false,
            currentUploadId: null,
            chunkSize: 80 * 1024 * 1024, // 80MB分片大小
            uploadedChunks: 0,
            totalChunks: 0,
            uploadProgress: {
                percentage: 0,        // 百分比
                uploadedChunks: 0,    // 已上传分片数
                totalChunks: 0,       // 总分片数
                uploadedSize: 0,      // 已上传字节数
                totalSize: 0,         // 总文件大小
                isUploading: false,   // 是否正在上传
                currentChunk: 0,      // 当前上传的分片
                speed: '0 KB/s',      // 上传速度
                remainingTime: '计算中...' // 剩余时间
            }
        };
    },
    created() {
        this.getMore();
    },
    methods: {
        uploadHandel(e) {
            this.form.file = e.file;
            console.log(`选择文件: ${e.file.name}, 大小: ${(e.file.size / 1024 / 1024).toFixed(2)}MB`);
        },
        // 生成上传ID
        generateUploadId() {
            return Date.now().toString(36) + Math.random().toString(36).substr(2, 9);
        },
        // 分片上传单个chunk
        async uploadChunk(chunk, chunkIndex, totalChunks, uploadId, fileName) {
            const formData = new FormData();
            formData.append('chunk', chunk, `chunk_${chunkIndex}`);
            formData.append('chunkIndex', chunkIndex);
            formData.append('totalChunks', totalChunks);
            formData.append('uploadId', uploadId);
            formData.append('fileName', fileName);

            // 重试逻辑
            let retries = 0;
            const maxRetries = 3;

            while (retries <= maxRetries) {
                try {
                    console.log('走到这')
                    const response = await uploadChunkHandel(formData);

                    if (response.data.success) {
                        return response.data;
                    } else {
                        throw new Error(response.data.error || '上传失败');
                    }
                } catch (error) {
                    retries++;
                    if (retries > maxRetries) {
                        throw new Error(`分片 ${chunkIndex + 1} 上传失败: ${error.message}`);
                    }

                    // 指数退避重试
                    await new Promise(resolve => setTimeout(resolve, Math.pow(2, retries) * 1000));
                    console.log(`分片 ${chunkIndex + 1} 重试第 ${retries} 次`);
                }
            }
        },

        // 合并分片
        async mergeChunks(uploadId, fileName, totalChunks, description) {
            const response = await mergeChunksHandel({
                uploadId,
                fileName,
                totalChunks,
                content: description
            })
                 

            return response.data;
        },

        // 分片上传主方法
        async uploadInChunks(file, description) {
            console.log(description,'description')
            const uploadId = this.generateUploadId();
            const totalChunks = Math.ceil(file.size / this.chunkSize);

            // 初始化进度
            this.uploadProgress = {
                percentage: 0,
                uploadedChunks: 0,
                totalChunks: totalChunks,
                uploadedSize: 0,
                totalSize: file.size,
                isUploading: true,
                currentChunk: 0,
                startTime: Date.now()
            };

            console.log(`开始上传: ${file.name}, 大小: ${(file.size / 1024 / 1024).toFixed(2)}MB`);
            console.log(`分片数量: ${totalChunks}, 每片: ${(this.chunkSize / 1024 / 1024).toFixed(2)}MB`);

            try {
                // 依次上传每个分片
                for (let i = 0; i < totalChunks; i++) {
                    const start = i * this.chunkSize;
                    const end = Math.min(start + this.chunkSize, file.size);
                    const chunk = file.slice(start, end);

                    this.uploadProgress.currentChunk = i + 1;

                    console.log(`上传分片 ${i + 1}/${totalChunks}`);

                    // 上传单个分片
                    await this.uploadSingleChunk(chunk, i, totalChunks, uploadId, file.name);

                    // 更新进度
                    this.uploadProgress.uploadedChunks++;
                    this.uploadProgress.uploadedSize += chunk.size;
                    this.uploadProgress.percentage = Math.round((this.uploadProgress.uploadedChunks / totalChunks) * 100);

                    // 计算上传速度和剩余时间
                    this.calculateUploadStats();

                    console.log(`进度: ${this.uploadProgress.percentage}% (${this.uploadProgress.uploadedChunks}/${totalChunks})`);
                }

                console.log('开始合并文件...');
                this.uploadProgress.percentage = 100;

                // 合并分片
                const result = await this.mergeChunks(uploadId, file.name, totalChunks, description);

                this.uploadProgress.isUploading = false;
                console.log('上传完成!', result);

                return result;

            } catch (error) {
                this.uploadProgress.isUploading = false;
                throw error;
            }
        },
        // 计算上传统计信息
        calculateUploadStats() {
            const now = Date.now();
            const elapsed = (now - this.uploadProgress.startTime) / 1000; // 秒
            const uploadedMB = this.uploadProgress.uploadedSize / 1024 / 1024;
            const speed = uploadedMB / elapsed; // MB/s

            this.uploadProgress.speed = speed > 1
                ? `${speed.toFixed(1)} MB/s`
                : `${(speed * 1024).toFixed(0)} KB/s`;

            const remainingSize = this.uploadProgress.totalSize - this.uploadProgress.uploadedSize;
            const remainingSeconds = remainingSize / (speed * 1024 * 1024);

            if (remainingSeconds > 60) {
                this.uploadProgress.remainingTime = `${Math.ceil(remainingSeconds / 60)} 分钟`;
            } else {
                this.uploadProgress.remainingTime = `${Math.ceil(remainingSeconds)} 秒`;
            }
        },
        // 上传单个分片
        async uploadSingleChunk(chunk, chunkIndex, totalChunks, uploadId, fileName) {
            const formData = new FormData();
            formData.append('chunk', chunk, `chunk_${chunkIndex}`);
            formData.append('chunkIndex', chunkIndex);
            formData.append('totalChunks', totalChunks);
            formData.append('uploadId', uploadId);
            formData.append('fileName', fileName);

            let retries = 0;
            const maxRetries = 3;

            while (retries <= maxRetries) {
                try {
                    // 使用你的API调用方式
                    const response = await uploadChunkHandel(formData);

                    if (response && response.success) {
                        return response;
                    } else {
                        throw new Error(response?.error || '上传失败');
                    }
                } catch (error) {
                    retries++;
                    console.error(`分片 ${chunkIndex + 1} 上传失败 (尝试 ${retries}/${maxRetries + 1}):`, error.message);

                    if (retries > maxRetries) {
                        throw new Error(`分片 ${chunkIndex + 1} 上传失败: ${error.message}`);
                    }

                    // 等待后重试
                    await new Promise(resolve => setTimeout(resolve, Math.pow(2, retries) * 1000));
                }
            }
        },
        remeveFile() {
            this.form.file = "";
        },
        timeChange() {
            this.queryParams.dateRange.start = this.value1[0];
            this.queryParams.dateRange.end = this.value1[1];
            this.handleQuery();
        },
        getKeyByValue(object, value) {
            return Object.keys(object).find((key) => object[key] === value);
        },
        async getMore() {
            this.loading = true;
            let { data, total } = await findUploadPckageList(this.queryParams);
            this.loading = false;
            this.moreArr = data;
            this.total = total;
        },

        handleQuery() {
            this.queryParams.page = 1;
            this.getMore();
        },
        // 修改原有的 affirm 方法
        async affirm() {
            this.$refs["ruleForm"].validate(async (valid) => {
                if (!valid) return;

                let loading;
                try {
                    this.form.description = this.form.description.replace(/\r\n|\r|\n/g, '\\n');

                    // 文件类型检查
                    const fileType = ["ipa", "apk", "aab"];
                    const fileName = this.form.file.name.split(".");
                    const fileExt = fileName[fileName.length - 1];
                    const isTypeOk = fileType.indexOf(fileExt) >= 0;

                    if (!isTypeOk) {
                        this.$message.error(
                            `The file format is incorrect, please upload an ${fileType.join("/")} format file!`
                        );
                        return false;
                    }

                    // 检查文件大小，决定使用哪种上传方式
                    const fileSize = this.form.file.size;
                    const maxSingleUploadSize = 100 * 1024 * 1024; // 90MB

                    loading = this.$loading({
                        lock: true,
                        text: "准备上传...",
                        spinner: "el-icon-loading",
                        background: "rgba(0, 0, 0, 0.7)",
                    });
                    // 更新loading文本的定时器
                    const updateLoadingText = setInterval(() => {
                        if (loading && this.uploadProgress.isUploading) {
                            const text = `上传中... ${this.uploadProgress.percentage}% (${this.uploadProgress.uploadedChunks}/${this.uploadProgress.totalChunks}) ${this.uploadProgress.speed}`;
                            loading.setText(text);
                        } else {
                            clearInterval(updateLoadingText);
                        }
                    }, 500);
                    this.addLoading = true;
                    this.isUploading = true;

                    if (fileSize > maxSingleUploadSize) {
                        console.log('文件较大，使用分片上传');

                        // 更新loading文本的定时器
                        const updateLoadingText = setInterval(() => {
                            if (loading && this.isUploading) {
                                loading.setText(`Uploading in chunks... ${this.uploadProgress.percentage}% (${this.uploadProgress.uploadedChunks}/${this.uploadProgress.totalChunks}))`);
                            } else {
                                clearInterval(updateLoadingText);
                            }
                        }, 500);

                        // 分片上传
                        await this.uploadInChunks(this.form.file, this.form.description);
                        clearInterval(updateLoadingText);
                    } else {
                        console.log('文件较小，使用普通上传');

                        // 普通上传
                        let data = new FormData();
                        data.append("file", this.form.file);
                        data.append("content", this.form.description);
                        await upload(data);
                    }

                    this.addLoading = false;
                    this.isUploading = false;
                    this.$message.success("上传成功!");
                    this.getMore();
                    this.dialogVisible = false;
                    this.resetForm();

                } catch (error) {
                    console.error('上传失败:', error);
                    this.addLoading = false;
                    this.isUploading = false;
                    this.$message.error(`上传失败: ${error.message}`);
                } finally {
                    this.resetUploadState();
                    if (loading) {
                        loading.close();
                    }
                }
            });
        },

        openDialog() {
            this.form = {};
            this.dialogVisible = true;
        },
        handleEdit(i, row) {
            this.resetForm();
            this.resetUploadState();
            this.dialogVisible = true;
        },

        // 重置表单
        resetForm() {
            this.form.description = "";
            this.form.file = "";
            if (this.$refs.upload) {
                this.$refs.upload.clearFiles();
            }
        },

        // 重置上传状态
        resetUploadState() {
            this.uploadProgress = 0;
            this.uploadedChunks = 0;
            this.totalChunks = 0;
            this.currentUploadId = null;
            this.addLoading = false;
            this.isUploading = false;
        },
        handleDelete(index, row) {
            this.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "error",
            }).then(async () => {
                await deleteTemplateType({ id: row.id });
                this.getMore();
                this.$message({
                    message: "删除成功！",
                    type: "success",
                });
            });
        },
        resetQuery() {
            this.queryParams.state = null;
            this.queryParams.package_name = null;
            this.queryParams.dateRange.start = null;
            this.queryParams.dateRange.end = null;
            this.queryParams.page = 1;
            this.value1 = "";
            this.getMore();
        },
    },
};
</script>
<style lang="scss" scoped>
.boxs {
    padding: 20px;
}

::v-deep.el-input.is-disabled .el-input__inner {
    color: #333 !important;
}

::v-deep.el-textarea.is-disabled .el-textarea__inner {
    color: #333 !important;
}

::v-deep .el-upload {
    width: 100% !important;
}

::v-deep .el-upload-dragger {
    width: 100% !important;
}
</style>